package com.hrbxlh.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

/**
* -------------------------------------------------------
* Copyright (c) 2017, 鑫联华信息科技股份有限公司
* All rights reserved.
* FileName：FileUpload.java
* Description：文件上传util类。
* History：
* Date           Author               Desc
* 2017.3.28		  xzx                 建立
* -------------------------------------------------------
*/

public class FileUpload {

	Logger logger = Logger.getLogger(FileUpload.class.getName());
	
	/***@description 上传文件的方法
	 * @param 文件流
	 * @param 上传的文件的文件新名字
	 * @param 文件保存位置
	 * @param 是否转换word的标识   1转换  2不转换
	 * @return boolean true成功，false失败
	 * @throws Exception
	 */
	public Map<String,Object> fileUpload(CommonsMultipartFile file, String newName, String filePath, int convertMark) throws Exception{
		
		//20170622商莹将这个方法返回值改为map类型
		Map<String,Object> uploadMap = new HashMap<String,Object>();
		String resultPdf="";
		String resultDoc="";
		String resultHtml = "";
		try{
			//上传的文件名字
			String fileOriginalName =  file.getOriginalFilename();
			//上传的文件名字的分割数组
			String extArr [] = fileOriginalName.split("\\.");
			//如果传了文件
			if(!fileOriginalName.equals("")){
				logger.info("存在文件信息");
				//连接转换服务开始
				ObjectMapper mapper = new ObjectMapper();
				String[] keysArray = {"convert_server"};
				Map<String, Object> urlmap = ConfigFileUtil.getFileMessage("UtilFile.properties", keysArray);
				HttpHeaders headers = new HttpHeaders();
				MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
				headers.setContentType(type);
				//连接转换服务结束
				//建立路径加上新文件的名字
				String path = filePath + "/" + newName;
				//判断文件夹存不存在,不存在就创建
				File saveFile = new File(path);
				if (!saveFile.exists()) {
					File saveFileDir = new File(path.substring(0,path.lastIndexOf("\\") + 1));
					saveFileDir.mkdirs();
					saveFile = new File(path);
				}
				//上传的新文件的tostring
				String filePdf = String.valueOf(saveFile);
				//上传文件
				FileUtils.copyInputStreamToFile(file.getInputStream(), saveFile);
				logger.info("基础文件上传成功，文件名为："+saveFile.getName());
				//返回的新文件的名字
				resultPdf = newName;
				//需要转换word
				if(convertMark == 2){
					logger.info("编辑章节，转换html开始");
					//如果上传的是word文件.需要转换成html文件
					if(extArr[extArr.length-1].equals("doc") || extArr[extArr.length-1].equals("docx")){
						FileConvert pdfToHtml = new FileConvert();
						//pdf转换html 参数 文件前缀、已经上传的pdf文件名、
						//String htmlName = pdfToHtml.pdfConvertHtml(filePath, newName);
						/*  test 1220
						WordToHtmlUtil.convertWordToHtml(new File(filePath + "/" + newName), filePath + "/"+getFileName(newName)+".html");
						*/
						//转换html开始
						Map<String, Object> wordMap = new HashMap<String, Object>();
						wordMap.put("originFile", filePath + "/" + newName);
						wordMap.put("destinFile", filePath + "/"+getFileName(newName)+".html");
						HttpEntity<String> formEntity = new HttpEntity<String>(mapper.writeValueAsString(wordMap), headers);
						RestTemplate restTemplate = new RestTemplate();
						wordMap = restTemplate.postForObject(urlmap.get("convert_server").toString()+"/convertWordToHtml", formEntity, wordMap.getClass());
						if(wordMap == null || wordMap.get("result").equals("fail")){
							throw new Exception("word to html error");
						}
						//转换html结束
						//返回html文件名
						resultHtml = getFileName(newName)+".html";
						resultDoc = newName;
					}
					//如果上传的是ppt需要将ppt转换为pdf,字段放到html字段里
					logger.info("编辑章节转换html结束");
				}else if(convertMark == 3){
					logger.info("编辑章节，转换pdf开始");
					if(extArr[extArr.length-1].equals("pptx")){
						//PPTConvertPdfUtil.convertPptToPdf(filePath + "/" + newName, filePath + "/"+getFileName(newName)+".pdf");
						//转换pdf开始
						Map<String, Object> wordMap = new HashMap<String, Object>();
						wordMap.put("originFile", filePath + "/" + newName);
						wordMap.put("destinFile", filePath + "/"+getFileName(newName)+".pdf");
						HttpEntity<String> formEntity = new HttpEntity<String>(mapper.writeValueAsString(wordMap), headers);
						RestTemplate restTemplate = new RestTemplate();
						wordMap = restTemplate.postForObject(urlmap.get("convert_server").toString()+"/convertPPTToPDF", formEntity, wordMap.getClass());
						if(wordMap == null || wordMap.get("result").equals("fail")){
							throw new Exception("ppt to pdf error");
						}
						//转换pdf结束
						logger.info("编辑章节，转换pdf结束，文件名为："+getFileName(newName)+".pdf");
						resultHtml =getFileName(newName)+".pdf";
					}
				}
			}
			uploadMap.put("result", resultPdf);
			uploadMap.put("resultDoc", resultDoc);
			uploadMap.put("resultHtml", resultHtml);
		}catch(Exception e){
			throw e;
		}
		return uploadMap;
	}


	/**
	 * @description 获取文件名字不带后缀
	 * @param 文件名带后缀的
	 * */
	public static String getFileName(String fileNameAll){
		StringBuffer sb = new StringBuffer();
		String nameArr [] = fileNameAll.split("\\.");
		for(int i = 0; i < nameArr.length - 1; i++){
			sb.append(nameArr[i]);
		}
		return sb.toString();
	}


	
	/***@description 将pdf转为word
	 * @param pdf文件
	 * @param 路径
	 * @throws Exception
	 */
	public  void readPdf(String file,String wordPath)
	       throws DocumentException, IOException {
		try(FileOutputStream  fike = new FileOutputStream(wordPath);
			PrintWriter writer = new PrintWriter(fike)) {
			inspect(writer,file); //调用读取方法
		}
	   }
	   
	/***@description 将pdf转为word
	 * @param pdf文件
	 * @param 路径
	 * @throws Exception
	 */
	public  void inspect(PrintWriter writer, String filename)

	       throws IOException {
		PdfReader reader = new PdfReader(filename); //读取pdf所使用的输出流
		try {
			int num = reader.getNumberOfPages();//获得页数
			String content = "";  //存放读取出的文档内容

			for (int i = 1; i <= num; i++) {
               content += PdfTextExtractor.getTextFromPage(reader, i); //读取第i页的文档内容
          }

			writer.write(content);//写入文件内容
			writer.flush();
		}finally {
			reader.close();
			writer.close();
		}

	}
	
	/***
	 * @description 删除某文件
	 * @param 文件路径(最后一级要加"/")
	 * @param 文件名
	 * @return 成功失败
	 */
	public boolean deleteFileOnly(String path,String fileName)throws Exception {
		
		boolean result = false;
		try{
			File file = new File(path+fileName);
			if(file.isFile()){
				file.delete();
			}
			result = true;
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}
		return result;
	}

	/***
	 * @description 删除某文件
	 * @param 文件路径(最后一级要加"/")
	 * @param 文件名
	 * @return 成功失败
	 */
	public boolean deleteFileOnly(String filepath)throws Exception {

		boolean result = false;
		try{
			File file = new File(filepath+"/");
			if(file.isFile()){
				file.delete();
			}
			result = true;
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}
		return result;
	}
	
	/***@description 构建上传文件的参数，并将文件上传
	 * @param 文件流
	 * @param request
	 * @param 上传类型   1正常课程   2学生作业等
	 * @param convertMark 是否转换word的标识  0不转换  1转换word(未使用)  2转换html   3转换pdf
	 * @return String 文件名
	 * @throws Exception
	 */
	public Map<String,Object> fileUploadParam(CommonsMultipartFile file, HttpServletRequest request,int pathType, int convertMark,String courseMark) throws Exception{
		
		//20170622商莹将这个方法返回值改为map类型  
		Map<String,Object> uploadMap = new HashMap<String,Object>();
		try{ 
			String fileOriginalName =  file.getOriginalFilename();
			String fileNameZD = fileOriginalName.split("\\.")[0] +courseMark +  "."+ fileOriginalName.split("\\.")[fileOriginalName.split("\\.").length-1].toLowerCase();
			String filePath = "";
			//文件前缀路径
			String[] keysArray = {"server_address", "project_name","tomcatUrl"};
			Map<String, Object> urlmap = ConfigFileUtil.getFileMessage("UtilFile.properties", keysArray);
			String url = (String)urlmap.get("tomcatUrl")+(String)urlmap.get("project_name")+"upload/";
			//测试用的
//			String url = "C:\\Users\\Administrator\\Desktop\\xxbg\\";
			if(pathType == 1){
				filePath = url+"course";
			}else{
				filePath = url+"stuwork";
			}
			logger.info("编辑章节基础操作已做好，执行转换。");
			uploadMap = this.fileUpload(file, fileNameZD, filePath, convertMark);
		}catch(Exception e){
			throw e;
		}
		return uploadMap;
	}
	
	/***@description 删除课程上传的文件
	 * @param 文件流
	 * @param request
	 * @return 成功失败标识
	 * @throws Exception
	 */
	public boolean deleteFile(List<Map<String, Object>> chapterList,CommonsMultipartFile courseware,CommonsMultipartFile video,CommonsMultipartFile homework,CommonsMultipartFile courseMaterial,CommonsMultipartFile courseAnswer, CommonsMultipartFile testDocName) throws Exception{
		
		boolean result = false;
		try{
			if(chapterList != null){
				if(chapterList.size() != 0){
					String[] keysArray = {"server_address", "project_name","tomcatUrl"};
					Map<String, Object> pathMap = ConfigFileUtil.getFileMessage("UtilFile.properties", keysArray);
					for(int i=0; i< chapterList.size(); i++){
						String path = (String)pathMap.get("tomcatUrl") + (String)pathMap.get("project_name")+"upload/course/";
						//修改的时候，没上传，就不删除文件
						if(!courseware.getOriginalFilename().equals("")){
							String coursewareName = (String)chapterList.get(i).get("coursewareName");
							this.deleteFileOnly(path, coursewareName);
							String coursewareNameHtml = (String)chapterList.get(i).get("coursewareNameHtml");
							this.deleteFileOnly(path, coursewareNameHtml);
						}
						if(!video.getOriginalFilename().equals("")){
							String videoName = (String)chapterList.get(i).get("videoName");
							this.deleteFileOnly(path, videoName);
						}
						if(!homework.getOriginalFilename().equals("")){
							String homeworkName = (String)chapterList.get(i).get("homeworkName");
							String homeworkNameHtml = (String)chapterList.get(i).get("homeworkNameHtml");
							String homeworkNameDoc = (String) chapterList.get(i).get("homeworkNameDoc");
							this.deleteFileOnly(path, homeworkName);
							this.deleteFileOnly(path, homeworkNameHtml);
							this.deleteFileOnly(path, homeworkNameDoc);
						}
						if(!courseMaterial.getOriginalFilename().equals("")){
							String courseMaterialName = (String)chapterList.get(i).get("courseMaterialName");
							String courseMaterialNameHtml = (String)chapterList.get(i).get("courseMaterialNameHtml");
							this.deleteFileOnly(path, courseMaterialName);
							this.deleteFileOnly(path, courseMaterialNameHtml);
						}
						if(!courseAnswer.getOriginalFilename().equals("")){
							String courseAnswerName = (String)chapterList.get(i).get("courseAnswerName");
							String courseAnswerNameHtml = (String)chapterList.get(i).get("courseAnswerNameHtml");
							this.deleteFileOnly(path, courseAnswerName);
							this.deleteFileOnly(path, courseAnswerNameHtml);
						}
						if(!testDocName.getOriginalFilename().equals("")){
							String testDocNameUse = (String)chapterList.get(i).get("testDocName");
							String testNameHtml = (String)chapterList.get(i).get("testNameHtml");
							this.deleteFileOnly(path, testDocNameUse);
							this.deleteFileOnly(path, testNameHtml);
						}

					}
				}
			}
			result = true;
		}catch(Exception e){
			throw e;
		}
		return result;
	}

	/**
	 * @description 通过传过来的文件集合，要取的对应后缀名集合（二维数组形式），每个文件代表的名字集合来判断上传的文件格式是否符合规定
	 * @param files 要验证的文件流集合
	 * @param postfixArr 每个文件顺序对应的文件可能上传的后缀集合（每个文件可以有多个）
	 * @param nameArr 每个文件对应的名字信息集合，用于返回失败信息
	 * @return 返回成功失败信息，以及具体失败信息
	 * */
	public Map<String, Object> getFilePostfixReasonableMark(CommonsMultipartFile[] files, String[][] postfixArr, String[] nameArr){
		Map<String, Object> map = new HashMap<String, Object>();
		boolean mark = false;
		String pName;
		for(int file = 0; file < files.length; file++){
			mark = false;
			//如果上传了文件则进行验证
			if(!files[file].getOriginalFilename().equals("")) {
				pName = files[file].getOriginalFilename().split("\\.")[files[file].getOriginalFilename().split("\\.").length - 1];
				for (int postfix = 0; postfix < postfixArr[file].length; postfix++) {
					if (pName.equals(postfixArr[file][postfix])) {
						mark = true;
						break;
					}
				}
				if (!mark) {
					map.put("result", "fail");
					map.put("failMsg", nameArr[file] + "的文件类型上传错误，请上传" + StringUtils.join(postfixArr[file], ",") + "类型的文件");
					return map;
				}
			}
		}
		map.put("result","success");
		return map;
	}

	//单位MB
	public static Map<String, Object> checkFileSize(CommonsMultipartFile[] files, double fileSize[]){
		Map<String, Object> map = new HashMap<>();
		if(null != files && 0 != files.length){
			for(int i = 0; i < files.length; i++){
				if(!"".equals(files[i].getOriginalFilename())){
					if((files[i].getSize()/1024/1024) > fileSize[i]){
						map.put("result", false);
						map.put("failMsg", files[i].getOriginalFilename()+" 文件大于"+fileSize[i]+"M,超出限制");
						return map;
					}
				}
			}
		}
		map.put("result", true);
		return map;
	}

	/*
	  * 删除指定文件夹下所有文件
     *
			 * @param path 文件夹完整绝对路径
     * @return
			 */
	public static  boolean delAllFile(String path) {
		boolean flag = false;
		File file = new File(path);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);// 再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}

	/***
	 * 删除文件夹
	 *
	 * @param folderPath文件夹完整绝对路径
	 */
	public  static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			java.io.File myFilePath = new java.io.File(filePath);
			myFilePath.delete(); // 删除空文件夹
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
